using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

using DbSharper.Library.Data;
using DbSharper.Library.Model;

using DbSharper.Core.Enums;
using DbSharper.Core.Models.Core;
using DbSharper.Core.Models.Dbo;

namespace DbSharper.Core.Models.Core
{
	#region Model Produt

	/// <summary>
	/// Business model used to model Produt item.
	/// </summary>
	[Serializable]
	public partial class ProdutItem : ItemBase, IJson
	{
		#region Fields
		
		private int id;
		private string name;
		private decimal price;

		#endregion

		#region Constructors

		/// <summary>
		/// Default constructor.
		/// </summary>
		public ProdutItem() : base() { }

		/// <summary>
		/// Constructor using IDataRecord.
		/// </summary>
		public ProdutItem(IDataRecord record) : base(record) { }

		#endregion

		#region Methods

		/// <summary>
		/// Load field value through IDataRecord.
		/// </summary>
		/// <param name="record">Data Record.</param>
		/// <param name="fieldName">Field name.</param>
		/// <param name="index">Index of field.</param>
		public override void LoadField(IDataRecord record, string fieldName, int index)
		{
			switch (fieldName)
			{
				case "Id":
					{
						if (!record.IsDBNull(index))
						{
							this.id = record.GetInt32(index);
						}
						
						return;
					}
				case "Name":
					{
						if (!record.IsDBNull(index))
						{
							this.name = record.GetString(index);
						}
						
						return;
					}
				case "Price":
					{
						if (!record.IsDBNull(index))
						{
							this.price = record.GetDecimal(index);
						}
						
						return;
					}
				default:
					{
						AddValue(fieldName, record.GetValue(index));

						return;
					}
			}
		}
		
		/// <summary>
		/// Get value of property by property name.
		/// </summary>
		/// <param name="propertyName">Property name.</param>
		/// <return>Value of property.</return>
		public override object GetPropertyValue(string propertyName)
		{
			switch (propertyName)
			{
				case "Id":
					return this.id;
				case "Name":
					return this.name;
				case "Price":
					return this.price;
				default:
					return null;
			}
		}

		/// <summary>
		/// Creates a deep copy of the ProdutItem.
		/// </summary>
		public ProdutItem Clone()
		{
			ProdutItem item = new ProdutItem()
			{
				Id = this.id,
				Name = this.name,
				Price = this.price
			};
			
			return item;
		}

		/// <summary>
		/// Get JSON string of this item.
		/// </summary>
		/// <returns>JSON string.</returns>
		public string ToJson()
		{
			JsonBuilder jb = new JsonBuilder(this);
			
			jb.Append("Id", this.id);
			jb.Append("Name", this.name);
			jb.Append("Price", this.price);
			
			if (this.ExtendedFields != null)
			{
				foreach(string fieldName in this.ExtendedFields.Keys)
				{
					jb.Append(fieldName, this.ExtendedFields[fieldName]);
				}
			}
			
			return jb.ToString();
		}

		/// <summary>
		/// Return name of this class.
		/// </summary>
		public override string ToString()
		{
			return "ProdutItem";
		}
		
		#endregion
		
		#region Extensibility Methods
				
		/// <summary>
		/// Invoked before Id changed.
		/// </summary>
		partial void OnIdChanging(int value);

		/// <summary>
		/// Invoked after Id changed.
		/// </summary>
		partial void OnIdChanged();
				
		/// <summary>
		/// Invoked before Name changed.
		/// </summary>
		partial void OnNameChanging(string value);

		/// <summary>
		/// Invoked after Name changed.
		/// </summary>
		partial void OnNameChanged();
				
		/// <summary>
		/// Invoked before Price changed.
		/// </summary>
		partial void OnPriceChanging(decimal value);

		/// <summary>
		/// Invoked after Price changed.
		/// </summary>
		partial void OnPriceChanged();
		
		#endregion
		
		#region Properties
		
		/// <summary>
		/// Summary of Id.
		/// </summary>
		public int Id
		{
			get
			{
				return this.id;
			}

			set
			{
				if (this.id != value)
				{
					OnIdChanging(value);
					
					this.id = value;
					this.SetPropertyChanged("Id");
					
					OnIdChanged();
				}
			}
		}
		
		/// <summary>
		/// Summary of Name.
		/// </summary>
		public string Name
		{
			get
			{
				return this.name;
			}

			set
			{
				if (this.name != value)
				{
					OnNameChanging(value);
					
					this.name = value;
					this.SetPropertyChanged("Name");
					
					OnNameChanged();
				}
			}
		}
		
		/// <summary>
		/// Summary of Price.
		/// </summary>
		public decimal Price
		{
			get
			{
				return this.price;
			}

			set
			{
				if (this.price != value)
				{
					OnPriceChanging(value);
					
					this.price = value;
					this.SetPropertyChanged("Price");
					
					OnPriceChanged();
				}
			}
		}
		
		#endregion
	}

	/// <summary>
	/// Business model collection used to model Produt items.
	/// </summary>
	[Serializable]
	public partial class ProdutCollection : CollectionBase<Models.Core.ProdutItem>, IJson
	{
		#region Fields
		
		private Dictionary<int, int> idItemIndexer;

		#endregion

		#region Constructors
		
		public ProdutCollection() : base() { }

		#endregion
		
		#region Methods
		
		/// <summary>
		/// Get series of Id string joinned by ",".
		/// </summary>
		/// <returns>Id string.</returns>
		public string GetIds()
		{
			return GetIds(",");
		}

		/// <summary>
		/// Get series of Id string joinned by separator.
		/// </summary>
		/// <param name="separator">Separator.</param>
		/// <returns>Id string.</returns>
		public string GetIds(string separator)
		{
			StringBuilder sb = new StringBuilder();

			int length = this.Count;

			for (int i = 0; i < length; i++)
			{
				sb.Append(this[i].Id);
				sb.Append(separator);
			}

			if (length > 0)
			{
				sb.Length -= separator.Length;
			}

			return sb.ToString();
		}

		/// <summary>
		/// Get Produt item by id.
		/// </summary>
		/// <param name="id">Id.</param>
		/// <returns>Produt item.</returns>
		public ProdutItem GetById(int id)
		{
			if (idItemIndexer == null)
			{
				idItemIndexer = new Dictionary<int, int>();

				for (int i = 0, length = this.Count; i < length; i++)
				{
					idItemIndexer.Add(this[i].Id, i);
				}
			}
			
			if (!idItemIndexer.ContainsKey(id))
			{
				return null;
			}

			return this[idItemIndexer[id]];
		}

		/// <summary>
		/// Creates a deep copy of the ProdutCollection.
		/// </summary>
		public ProdutCollection Clone()
		{
			ProdutCollection col = new ProdutCollection();

			for (int i = 0, length = this.Count; i < length; i++)
			{
				col.Add(this[i].Clone());
			}

			return col;
		}
		
		/// <summary>
		/// Get JSON string of this collection.
		/// </summary>
		/// <returns>JSON string.</returns>
		public string ToJson()
		{
			JsonBuilder jb = new JsonBuilder(this);

			return jb.ToString();
		}

		/// <summary>
		/// Return name of this class.
		/// </summary>
		public override string ToString()
		{
			return "ProdutCollection";
		}
		
		#endregion
	}

	#endregion
}
